package org.xbdframework.boot.autoconfigure.quartz;

import javax.sql.DataSource;

import org.springframework.boot.autoconfigure.quartz.SchedulerFactoryBeanCustomizer;
import org.springframework.context.annotation.Import;
import org.xbdframework.boot.autoconfigure.task.XbdTaskExecutionAutoConfiguration;
import org.xbdframework.scheduling.quartz.QuartzTaskHandler;
import org.xbdframework.scheduling.quartz.AutowireCapableXbdBeanJobFactory;
import org.xbdframework.scheduling.quartz.handler.DefaultQuartzTaskHandler;

import org.quartz.Scheduler;

import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;

/**
 * Quartz Scheduler自动化配置 {@link EnableAutoConfiguration Auto-configuration}
 *
 * @author luas
 * @since 1.5.0
 */
@Configuration
@ConditionalOnClass({ Scheduler.class, SchedulerFactoryBean.class,
		QuartzTaskHandler.class, DefaultQuartzTaskHandler.class })
@EnableConfigurationProperties(XbdQuartzProperties.class)
@AutoConfigureAfter({ DataSourceAutoConfiguration.class,
		HibernateJpaAutoConfiguration.class, XbdTaskExecutionAutoConfiguration.class })
@Import(QuartzTaskHandlerConfiguration.class)
public class XbdQuartzAutoConfiguration {

	private XbdQuartzProperties properties;

	private final ApplicationContext applicationContext;

	public XbdQuartzAutoConfiguration(XbdQuartzProperties properties,
										ApplicationContext applicationContext) {
		this.properties = properties;
		this.applicationContext = applicationContext;
	}

	@Bean
	public AutowireCapableXbdBeanJobFactory autowireCapableXbdBeanJobFactory() {
		return new AutowireCapableXbdBeanJobFactory(this.applicationContext);
	}

	@Bean
	public SchedulerFactoryBeanCustomizer propertiesCustomizer() {
		return (schedulerFactoryBean) -> schedulerFactoryBean.setApplicationContextSchedulerContextKey(
				this.properties.getApplicationContextSchedulerContextKey());
	}

	/**
	 * 默认使用系统数据源
	 */
	@Configuration
	@ConditionalOnSingleCandidate(DataSource.class)
	protected static class SystemDatasourceTypeConfiguration {

		@Bean
		@Order(0)
		public SchedulerFactoryBeanCustomizer dataSourceCustomizer(
				XbdQuartzProperties properties, DataSource dataSource,
				ObjectProvider<PlatformTransactionManager> transactionManager) {
			return (schedulerFactoryBean) -> {
				if (properties.getDataSourceType() == DataSourceType.SYSTEM) {
					schedulerFactoryBean.setDataSource(dataSource);
					PlatformTransactionManager txManager = transactionManager
							.getIfUnique();
					if (txManager != null) {
						schedulerFactoryBean.setTransactionManager(txManager);
					}
				}
			};
		}

	}

}
